<?php

namespace pmvc\data;

use pmvc\DataSource;
use Exception;

class MysqlDataSource 
	implements DataSource {
	
	private $config		= FALSE;
	private $link		= FALSE;
	
	public function configure($config) {
		$this->config = $config;
	}
	
	private function get_last_error() {
		return "errno ".mysql_errno()." - ".mysql_error();
	}
	
	private function buildQuery($sql, $args) {
	    for ($i=0; $i<count($args); $i++) {
            $sql = str_replace("{".$i."}", $args[$i], $sql);
        }
        return $sql;
	}
	
	public function connect() {
		if ($this->link!==FALSE) {
			return;
		}
		if (empty($this->config["port"])) {
			$this->config["port"] = "3306";
		}
		if (empty($this->config["client_flags"])) {
			$this->config["client_flags"] = 0;
		}
		$this->link = mysql_connect(
			$this->config["host"].":".$this->config["port"],
			$this->config["username"],
			$this->config["password"],
			TRUE,
			$this->config["client_flags"]);
		if ($this->link===FALSE) {
			throw new Exception(pmvc_pstring(
				"Connection failed: {0}", $this->get_last_error()));
		}
		if (mysql_select_db($this->config["database"], $this->link)===FALSE) {
			throw new Exception(pmvc_pstring(
				"Selecting database failed: {0}", $this->get_last_error()));
		}
	}
	
	public function escape($str) {
		return mysql_escape_string($str);
	}
	
	public function query() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        pmvc_logdebug("Executing query: {0}", $sql);
        $ret = mysql_query($sql, $this->link);
        if ($ret===FALSE) {
			throw new Exception(pmvc_pstring(
				"Query failed: {0}", $this->get_last_error()));
        }
        return $ret;
	}
	
	public function update() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        pmvc_logdebug("Executing update: {0}", $sql);
        $ret = mysql_query($sql, $this->link);
        if ($ret===FALSE) {
			throw new Exception(pmvc_pstring(
				"Query failed: {0}", $this->get_last_error()));
        }
        return $ret;
	}
	
	public function lastInsertId() {
		$ret = mysql_insert_id($this->link);
        if ($ret===FALSE) {
			throw new Exception(pmvc_pstring(
				"Getting insert id failed: {0}", $this->get_last_error()));
        }
        return $ret;
	}
	
	public function querySingle() {
		$a = func_get_args();
        $res = call_user_func_array(array($this,"query"), $a);
        $ret = $this->numberOfRows($res)>0 
        	? $this->fetchRowObject($res)
        	: FALSE;
        $this->freeResult($res);
        return $ret;
	}
	
	public function numberOfRows($res) {
		$ret = mysql_num_rows($res);
        if ($ret===FALSE) {
			throw new Exception(pmvc_pstring(
				"Getting number of rows failed: {0}", $this->get_last_error()));
        }
        return $ret;
	}
	
	public function fetchRowObject($res) {
		return mysql_fetch_object($res);
	}
	
	public function numberOfRowsAffectedRows($res) {
		return mysql_affected_rows($res);
	}
	
	public function fetchRowObjects($res) {
		$objs = Array();
		while (($obj = $this->fetchRowObject($res))!==FALSE) {
			$objs[] = $obj;
		}
		return $objs;
	}
	
	public function freeResult($res) {
		$ret = mysql_free_result($res);
        if ($ret===FALSE) {
			throw new Exception(pmvc_pstring(
				"Freeing result failed: {0}", $this->get_last_error()));
        }
        return $ret;
	}
	
}

?>